package com.ywx.intelligentaicodegeneration.core;

import cn.hutool.core.util.StrUtil;
import com.ywx.intelligentaicodegeneration.ai.AiCodeGeneratorService;
import com.ywx.intelligentaicodegeneration.ai.AiCodeGeneratorServiceFactory;
import com.ywx.intelligentaicodegeneration.ai.model.HtmlCodeResult;
import com.ywx.intelligentaicodegeneration.ai.model.MultiFileCodeResult;
import com.ywx.intelligentaicodegeneration.core.parser.CodeParserExecutor;
import com.ywx.intelligentaicodegeneration.core.saver.CodeFileSaverExecutor;
import com.ywx.intelligentaicodegeneration.exception.BusinessException;
import com.ywx.intelligentaicodegeneration.exception.ErrorCode;
import com.ywx.intelligentaicodegeneration.exception.ThrowUtils;
import com.ywx.intelligentaicodegeneration.mode.enums.CodeGenTypeEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * 代码生成门面类,给调用方提供代码生成功能,整合调用Ai与文件写入
 */
@Service
@Slf4j
public class AiCodeGeneratorFacade {

    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;
//    @Resource
//    private AiCodeGeneratorService aiCodeGeneratorService;

    /**
     * 统一的代码生成入口 根据生成类型生成代码并保存到文件
     *
     * @param userMessage 用户提示词
     * @param codeGenType 生成类型
     * @return 生成的代码保存目录
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum codeGenType, Long appId) {
        //从缓存中获取Ai代码生成器服务
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);
        ThrowUtils.throwIf(codeGenType == null || StrUtil.isBlank(userMessage), ErrorCode.PARAMS_ERROR, "用户提示词或生成类型为空");
        return switch (codeGenType) {
            case HTML -> {
                HtmlCodeResult htmlCodeResult = aiCodeGeneratorService.generateHtmlCode(userMessage);
                yield CodeFileSaverExecutor.executeSaver(htmlCodeResult, codeGenType,appId);
            }
            case MULTI_FILE -> {
                MultiFileCodeResult multiFileCodeResult = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                yield CodeFileSaverExecutor.executeSaver(multiFileCodeResult, codeGenType,appId);
            }
            default ->
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的生成类型:" + codeGenType.getValue());
        };

    }

    /**
     * 统一的代码生成入口(流式) 根据生成类型生成代码并保存到文件
     *
     * @param userMessage 用户提示词
     * @param codeGenType 生成类型
     * @return 生成的代码保存目录
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum codeGenType, Long appId) {
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);
        ThrowUtils.throwIf(codeGenType == null || StrUtil.isBlank(userMessage), ErrorCode.PARAMS_ERROR, "用户提示词或生成类型为空");

        return switch (codeGenType) {
            case HTML -> {
                Flux<String> codeFlux = aiCodeGeneratorService.generateHtmlCodeStream(userMessage);
                yield processCodeStream(codeFlux, codeGenType,appId);
            }
            case MULTI_FILE -> {
                Flux<String> codeFlux = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                yield processCodeStream(codeFlux, codeGenType,appId);
            }
            default ->
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的生成类型:" + codeGenType.getValue());
        };
    }


    /**
     * 处理代码流
     *
     * @param codeFlux    代码流
     * @param codeGenType 生成类型
     * @return 流式响应
     */
    private Flux<String> processCodeStream(Flux<String> codeFlux, CodeGenTypeEnum codeGenType,Long appId) {
        StringBuilder codeBuilder = new StringBuilder();

        //实时保存生成的代码
        return codeFlux.doOnNext(code -> {
            codeBuilder.append(code);
        }).doOnComplete(() -> {
            try {
                //保存生成的代码到文件
                Object parsedResult = CodeParserExecutor.executeParser(codeBuilder.toString(), codeGenType);
                File saveDir = CodeFileSaverExecutor.executeSaver(parsedResult, codeGenType,appId);
                log.info("代码保存目录成功:{}", saveDir.getAbsolutePath());
            } catch (Exception e) {
                log.error("代码保存失败: {}", e.getMessage());
            }
        });
    }


}
